import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class Sign {

	public static void main(String[] args) {
		if (args.length < 2) {
			System.out.println("参数不正确");
			return;
		}
		String url = args[0];
		String secert = args[1];
		String time;
		if (args.length == 3) {
			time = args[2];
		} else {
			time = System.currentTimeMillis() + "";
		}
		Map<String, String> params = getParamsFromUrl(url);
		System.out.println(getSignStr(params, secert, time));
	}

	/**
	 * 解析出url参数中的键值对 如 "index.jsp?Action=del&id=123"，解析出Action:del,id:123存入map中
	 *
	 * @param URL
	 *            url地址
	 * @return url请求参数部分
	 */
	public static Map<String, String> getParamsFromUrl(String URL) {
		Map<String, String> mapRequest = new HashMap<String, String>();

		String[] arrSplit = null;

		String strUrlParam = truncateUrlPage(URL);
		if (strUrlParam == null) {
			return mapRequest;
		}

		arrSplit = strUrlParam.split("[&]");
		for (String strSplit : arrSplit) {
			String[] arrSplitEqual = null;
			arrSplitEqual = strSplit.split("[=]");

			// 解析出键值
			if (arrSplitEqual.length > 1) {
				// 正确解析
				mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);

			} else {
				if (arrSplitEqual[0] != "") {
					// 只有参数没有值，不加入
					mapRequest.put(arrSplitEqual[0], "");
				}
			}
		}
		return mapRequest;
	}

	/**
	 * 去掉url中的路径，留下请求参数部分
	 *
	 * @param strURL
	 *            url地址
	 * @return url请求参数部分
	 */
	private static String truncateUrlPage(String strURL) {
		String strAllParam = null;
		String[] arrSplit = null;

		strURL = strURL.trim().toLowerCase();

		arrSplit = strURL.split("[?]");
		if (strURL.length() > 1) {
			if (arrSplit.length > 1) {
				if (arrSplit[1] != null) {
					strAllParam = arrSplit[1];
				}
			}
		}

		return strAllParam;
	}

	public static String getSignStr(Map<String, String> paramsMap, String secretSign, String time) {
		// 1排序
		LinkedHashMap<String, String> sortParams = new LinkedHashMap<>();
		Object[] key_arr = paramsMap.keySet().toArray();
		Arrays.sort(key_arr);
		for (Object key : key_arr) {
			try {
				sortParams.put(key.toString(), URLEncoder.encode(paramsMap.get(key).toString(), "UTF-8"));
			} catch (UnsupportedEncodingException e) {

				e.printStackTrace();
			}
		}
		// 2 hashmap.toString()
		StringBuilder result = new StringBuilder();
		for (Map.Entry<String, String> entry : sortParams.entrySet()) {
			if (result.length() > 0)
				result.append("&");
			result.append(entry.getKey());
			result.append("=");
			result.append(entry.getValue());
		}
		// 3 md5
		String resultMD5 = md5(result.toString().replace("*", "%2A").replace("%7E", "~").replace("+", "%20"));
		// 4 MD5+secret+time
		StringBuilder sbAppend = new StringBuilder();
		sbAppend.append(resultMD5);
		sbAppend.append(secretSign);
		sbAppend.append(time);
		// 5 MD5
		String md5Result = md5(sbAppend.toString());
		return md5Result;
	}

	/**
	 * md5加密方式
	 *
	 * @param s
	 * @return
	 */
	public final static String md5(String s) {
		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			byte[] strTemp = s.getBytes();
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			mdTemp.update(strTemp);
			byte[] md = mdTemp.digest();
			int j = md.length;
			char str[] = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (Exception e) {
			return null;
		}
	}

}
